package org.carabiner.infinitest.swingui;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;

import org.carabiner.infinitest.TestEvent;
import org.carabiner.infinitest.TestStatusListener;

/**
 * 
 * @author <a href="mailto:benrady@gmail.com"Ben Rady</a>
 */
class ResultTreeModel extends DefaultTreeModel implements TestStatusListener
{
  private static final long serialVersionUID = 1069669302994963691L;

  public ResultTreeModel()
  {
    super(new DefaultMutableTreeNode("Failures", true));
  }
  
  public void testCaseSucceeded(TestEvent event)
  {
    MutableTreeNode caseNode = findNode(getRoot(), event);
    if (caseNode != null)
      removeNodeFromParent(caseNode);
  }
  
  public void testFailed(TestEvent e)
  {
    MutableTreeNode caseNode = findNode(getRoot(), e);
    if (caseNode == null)    
      caseNode = addNode(e);
    TestTreeNode methodNode = findNode(caseNode, e);    
    if (methodNode == null)
      addMethodNode(caseNode, e);
    else
    {
      methodNode.updateNode(e);
      fireTreeNodesChanged(this, getPathToRoot(methodNode), null, new Object[]{methodNode});
    }
  }

  public void testError(TestEvent event)
  {
    testFailed(event);
  }
  
  public void testMethodSucceeded(TestEvent event)
  {
    MutableTreeNode caseNode = findNode(getRoot(), event);    
    if (caseNode != null)
    {
      MutableTreeNode methodNode = findNode(caseNode, event);
      if (methodNode != null)
        removeNodeFromParent(methodNode);
      if (caseNode.getChildCount() == 0)
        removeNodeFromParent(caseNode);
    }    
  }

  private MutableTreeNode addNode(TestEvent testEvent)
  {  
    MutableTreeNode caseNode = new TestTreeNode(testEvent);
    insertNodeInto(caseNode, getRootNode(), 0);
    return caseNode;
  }

  private void addMethodNode(MutableTreeNode caseNode, TestEvent testEvent)
  {    
    MutableTreeNode methodNode = new ResultTreeNode(testEvent);
    insertNodeInto(methodNode, caseNode, 0);    
  }

  private Object createUserObject(TestEvent e)
  {
    return e.getTestMethod();
  }
  
  private MutableTreeNode getRootNode()
  {
    return (MutableTreeNode)getRoot();
  }

  private TestTreeNode findNode(Object parentNode, TestEvent event)
  {
    for(int i = 0; i < getChildCount(parentNode); i++)
    {
      TestTreeNode node = (TestTreeNode) getChild(parentNode, i);
      if (node.isNodeForEvent(event))
        return node;
    }
    return null;
  }

  public int getTestCaseCount()
  {
    return getChildCount(getRoot());
  }

  public TreeNode getTestCase(int i)
  {
    return (TreeNode) getChild(getRoot(), i);
  }
}
